﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using PPIDesktopClient.General;
using PPIMobileInterface.Entities;
using PPIMobileInterface.Logic;
using PPIDesktopClient.Logic;
using PPIDesktopClient.Entities;
using PPIDesktopClient.Entities.Xml;
using System.Configuration;
using VMind.Global;
using PPIDesktopClient.Events;


namespace PPIDesktopClient.General
{
    public class UploadProcess
    {
        protected string m_DatabaseConnectionString;
        protected string m_DatabaseName;
        protected int m_AmountDatabasePoles = 0;
        protected int m_AmountDatabaseAssets = 0;
        protected int m_TotalUpload;
        protected BackgroundWorker m_UploaderWorker;
        protected List<EOutbox> m_DatabasesToUpload;
        protected EOutbox m_CurrentDatabase;
        protected string m_ErrorMessage;

        public List<EOutbox> DatabasesToUpload
        {
            get
            {
                return m_DatabasesToUpload;
            }
            set
            {
                m_DatabasesToUpload = value;
            }
        }

        public int TotalPoles
        {
            get { return m_AmountDatabasePoles; }
        }

        public int TotalAssets
        {
            get { return m_AmountDatabaseAssets; }
        }

        public string DatabaseName
        {
            get { return m_DatabaseName; }
        }

        public UploadProcess()
        {
            m_UploaderWorker = new BackgroundWorker();
            m_UploaderWorker.WorkerReportsProgress = true;
            m_UploaderWorker.WorkerSupportsCancellation = true;
            m_UploaderWorker.DoWork += new DoWorkEventHandler(UploaderWorker_DoWork);
            m_UploaderWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(UploaderWorker_RunWorkerCompleted);
            m_UploaderWorker.ProgressChanged += new ProgressChangedEventHandler(UploaderWorker_ProgressChanged);
            m_CurrentDatabase = null;
            m_DatabasesToUpload = new List<EOutbox>();
            //RefreshValues();

        }

        public virtual void RefreshValues()
        {
            if (m_DatabasesToUpload.Count > 0)
            {
                m_CurrentDatabase = m_DatabasesToUpload.Find(NotUplodaded);
                if (m_CurrentDatabase != null)
                {
                    m_DatabaseConnectionString = m_CurrentDatabase.ConnectionString;
                    m_DatabaseName = m_CurrentDatabase.Created.ToLongDateString();
                    m_AmountDatabaseAssets = LogicLayer.GetTotalAssets(m_DatabaseConnectionString);
                    m_AmountDatabasePoles = LogicLayer.GetTotalPoles(m_DatabaseConnectionString);

                }
            }
            else
            {
                m_CurrentDatabase = null;
                m_DatabaseConnectionString = "";
                m_AmountDatabaseAssets = 0;
                m_AmountDatabasePoles = 0;
            }
        }

        private static bool NotUplodaded(EOutbox s)
        {
            if (!s.IsDataUploaded || !s.IsImagesUploaded)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public virtual bool HasNextUpload()
        {
            return (m_DatabasesToUpload.Find(NotUplodaded) != null);
        }

        public virtual void StartUpload()
        {
            if (HasNextUpload())
            {
                if (!m_UploaderWorker.IsBusy)
                {
                    RefreshValues();
                    if (m_CurrentDatabase != null)
                    {
                        if (!m_CurrentDatabase.IsDataUploaded)
                        {

                            UploadingNewDatabase(this, new EventArgs());
                            m_UploaderWorker.RunWorkerAsync();
                        }
                        else
                        {
                            m_CurrentDatabase.IsImagesUploaded = true;
                            m_CurrentDatabase.IsDataUploaded = true;
                            OnUploadedDatabase(this, new CompletedDatabaseArgs(m_CurrentDatabase));
                            StartUpload();
                        }
                    }
                }
            }
            else
            {
                OnUploaderCompleted(this, new EventArgs());
            }
        }

        public virtual void StopProcess()
        {
            if (m_UploaderWorker != null)
                m_UploaderWorker.CancelAsync();
        }

        protected virtual void Upload(DoWorkEventArgs e)
        {
            try
            {
                m_ErrorMessage = "";
                e.Result = "";
                bool _FoundedProblems = false;
                List<EVisit> _MobileVisits = LogicLayer.LoadAllCompleteVisits(m_DatabaseConnectionString, true);
                List<EVendor_Visit_XMissionStructure> m_VendorVisits = LVendor_Visit_XMissionStructure.GetListFromMobileVisits(_MobileVisits);

                StringBuilder _errorMessage = new StringBuilder();
                foreach (EVendor_Visit_XMissionStructure v in m_VendorVisits)
                {
                    string message = "";
                    if (!LogicLayer.CheckNullablePositions(v.Id, v.ConnectionString, ref message))
                    {
                        _FoundedProblems = true;
                        _errorMessage.Append(message);
                    }
                }
                if (!_FoundedProblems)
                {
                    XMLHelper.UpdateOpenedDatabase(Constants.K_XmlOutboxPath, m_CurrentDatabase.Id);
                    m_CurrentDatabase.IsOpenedDatabase = true;

                    m_TotalUpload = 0;
                    m_TotalUpload += m_VendorVisits.Count;
                    foreach (EVendor_Visit_XMissionStructure Visit in m_VendorVisits)
                    {
                        m_TotalUpload += Visit.Poles.Count;
                    }
                    Int32 _CountUploaded = m_TotalUpload;

                    Int32 _NewStructureServerID;
                    Int32 _NewPoleServerID;

                    foreach (EVendor_Visit_XMissionStructure Visit in m_VendorVisits)
                    {
                        if (Visit.StructureServerID == Int32.MinValue)
                        {
                            _NewStructureServerID = LVendor_Visit_XMissionStructure.UploadStructure(Visit);
                            if (_NewStructureServerID > 0)
                                LogicLayer.UpdateStructureServerID(_NewStructureServerID, Visit.Id, m_DatabaseConnectionString);
                        }
                        else
                        {
                            _NewStructureServerID = Visit.StructureServerID;
                        }
                        if (m_UploaderWorker.CancellationPending)
                        {
                            e.Cancel = true;
                            return;
                        }
                        foreach (EVendor_Visit_XMissionStructures_Pole Pole in Visit.Poles)
                        {
                            if (Pole.PoleServerID == Int32.MinValue && _NewStructureServerID > 0)
                            {
                                _NewPoleServerID = LVendor_Visit_XMissionStructures_Pole.UploadPole(Pole, _NewStructureServerID);
                                if (_NewPoleServerID > 0)
                                    LogicLayer.UpdatePoleServerID(_NewPoleServerID, Pole.Id, m_DatabaseConnectionString);
                                System.Threading.Thread.Sleep(ConvertHelper.ToInt32(ConfigurationManager.AppSettings["TimeWaitUpPoles"]));
                            }
                            _CountUploaded--;
                            m_UploaderWorker.ReportProgress(ReportProgress(_CountUploaded));
                            if (m_UploaderWorker.CancellationPending)
                            {
                                e.Cancel = true;
                                return;
                            }
                        }
                        _CountUploaded--;
                        m_UploaderWorker.ReportProgress(ReportProgress(_CountUploaded));
                        System.Threading.Thread.Sleep(ConvertHelper.ToInt32(ConfigurationManager.AppSettings["TimeWaitUpStructures"]));
                    }
                }
                else
                {
                    m_ErrorMessage = _errorMessage.ToString();
                    e.Cancel = true;
                }


            }
            catch (Exception ex)
            {
                m_ErrorMessage = ex.Message;
                e.Cancel = true;
            }


        }

        protected int ReportProgress(int _CountUploaded)
        {
            int _Progress;
            try
            {
                _Progress = ((m_TotalUpload - _CountUploaded) * 100) / m_TotalUpload;
            }
            catch (Exception)
            {
                _Progress = 0;
            }
            return _Progress;
        }

        #region Uploader Events

        void UploaderWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            OnUploaderProgressChanged(sender, e);
        }

        protected virtual void UploaderWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!e.Cancelled)
            {
                if (!string.IsNullOrEmpty(m_DatabaseConnectionString) && m_CurrentDatabase != null)
                {
                    XMLHelper.UpdateFolderNode(Constants.K_XmlOutboxPath, m_CurrentDatabase.Id);
                    m_CurrentDatabase.IsDataUploaded = true;
                    m_CurrentDatabase.IsImagesUploaded = true;


                    OnUploadedDatabase(this, new CompletedDatabaseArgs(m_CurrentDatabase));
                    if (!HasNextUpload())
                    {
                        OnUploaderCompleted(sender, new EventArgs());
                    }
                    else
                    {
                        StartUpload();
                    }

                }
            }
            else
            {
                if (string.IsNullOrEmpty(m_ErrorMessage))
                    OnUploadCancelled(sender, new EventArgs());
                else
                    OnUploadCancelledByInformation(sender, new MessageArgs(m_ErrorMessage));
            }


        }

        void UploaderWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            Upload(e);
        }

        #endregion

        #region UploadProcess Events
        public event EventHandler<ProgressChangedEventArgs> UploaderProgressChanged;
        private void OnUploaderProgressChanged(object o, ProgressChangedEventArgs e)
        {
            // Safely invoke an event:
            if (UploaderProgressChanged != null)
            {
                UploaderProgressChanged(o, e);
            }
        }

        public event EventHandler UploaderCompleted;
        protected void OnUploaderCompleted(object o, EventArgs e)
        {
            // Safely invoke an event:
            if (UploaderCompleted != null)
            {
                UploaderCompleted(o, e);
            }
        }

        public event EventHandler UploadCancelled;
        protected void OnUploadCancelled(object o, EventArgs e)
        {
            // Safely invoke an event:
            if (UploadCancelled != null)
            {
                UploadCancelled(o, e);
            }
        }

        public event EventHandler UploadingNewDatabase;
        protected void OnUploadingNewDatabase(object o, EventArgs e)
        {
            // Safely invoke an event:
            if (UploadingNewDatabase != null)
            {
                UploadingNewDatabase(o, e);
            }
        }

        public event EventHandler<CompletedDatabaseArgs> UploadedDatabase;
        protected void OnUploadedDatabase(object o, CompletedDatabaseArgs e)
        {
            // Safely invoke an event:
            if (UploadedDatabase != null)
            {
                UploadedDatabase(o, e);
            }
        }

        public event EventHandler<MessageArgs> UploadCancelledByInformation;
        protected void OnUploadCancelledByInformation(object o, MessageArgs e)
        {
            // Safely invoke an event:
            if (UploadCancelledByInformation != null)
            {
                UploadCancelledByInformation(o, e);
            }
        }


        #endregion

    }
}
